home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 242 / Issue 242 - April 2008 - DPCS0408DVD.ISO / Software Money Savers / VirtualDub / Source / VirtualDub-1.7.7-src.7z / src / Kasumi / source / blt_reference_yuvrev.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-11-30  |  13.3 KB  |  486 lines

  1. #include <vd2/system/vdtypes.h>
  2. #include <vd2/system/vdstl.h>
  3. #include <vd2/Kasumi/pixmap.h>
  4. #include <vd2/Kasumi/pixmaputils.h>
  5. #include "blt_spanutils.h"
  6.  
  7. using namespace nsVDPixmapSpanUtils;
  8.  
  9. namespace {
  10.     // From Jim Blinn's "Dirty Pixels":
  11.     //
  12.     // Y  = .299R + .587G + .114B
  13.     // Cr = 0.713(R-Y)
  14.     // Cb = 0.564(B-Y)
  15.     //
  16.     // IY  = 219Y  + 16  = ((yt = 1052IR + 2065IG + 401IB) + 67584) >> 12
  17.     // ICr = 224Cr + 128 = (yt*2987 - 10507932IR + 2155872256) >> 24
  18.     // ICb = 224Cb + 128 = (yt*2363 - 8312025IB + 2155872256) >> 24
  19.  
  20.     void ConvertRGB32ToXVYU32(uint32 *dst, const uint8 *src, sint32 count) {
  21.         do {
  22.             const sint32 r  = src[2];
  23.             const sint32 g  = src[1];
  24.             const sint32 b  = src[0];
  25.             const sint32 yt = 1052*r + 2065*g + 401*b;
  26.             const sint32 y  = (yt + 67584) >> 4;                            // <<8 alignment shift
  27.             const sint32 cr = (10507932*r - yt*2987 + 2155872256U) >> 8;    // <<16 alignment shift
  28.             const sint32 cb = ( 8312025*b - yt*2363 + 2155872256U) >> 24;
  29.  
  30.             *dst++ = (y&0xff00) + cb + (cr&0xff0000);        // VYU order
  31.             src += 4;
  32.         } while(--count);
  33.     }
  34.  
  35.     void ConvertRGB24ToXVYU32(uint32 *dst, const uint8 *src, sint32 count) {
  36.         do {
  37.             const sint32 r  = src[2];
  38.             const sint32 g  = src[1];
  39.             const sint32 b  = src[0];
  40.             const sint32 yt = 1052*r + 2065*g + 401*b;
  41.             const sint32 y  = (yt + 67584) >> 4;                            // <<8 alignment shift
  42.             const sint32 cr = (10507932*r - yt*2987 + 2155872256U) >> 8;    // <<16 alignment shift
  43.             const sint32 cb = ( 8312025*b - yt*2363 + 2155872256U) >> 24;
  44.  
  45.             *dst++ = (y&0xff00) + cb + (cr&0xff0000);        // VYU order
  46.             src += 3;
  47.         } while(--count);
  48.     }
  49.  
  50.     void ConvertRGB16ToXVYU32(uint32 *dst, const uint16 *src, sint32 count) {
  51.         do {
  52.             const sint16 px = *src++;
  53.             const sint32 r  = (px & 0xf800) >> 11;
  54.             const sint32 g  = (px & 0x07e0) >> 5;
  55.             const sint32 b  = (px & 0x001f);
  56.             const sint32 yt = 8652*r + 8358*g + 3299*b;
  57.             const sint32 y  = (yt + 67584) >> 4;                            // <<8 alignment shift
  58.             const sint32 cr = (86436217*r - yt*2987 + 2155872256U) >> 8;
  59.             const sint32 cb = (68373108*b - yt*2363 + 2155872256U) >> 24;    // <<16 alignment shift
  60.  
  61.             *dst++ = (y&0xff00) + cb + (cr&0xff0000);        // VYU order
  62.         } while(--count);
  63.     }
  64.  
  65.     void ConvertRGB15ToXVYU32(uint32 *dst, const uint16 *src, sint32 count) {
  66.         do {
  67.             const sint16 px = *src++;
  68.             const sint32 r  = (px & 0x7c00) >> 10;
  69.             const sint32 g  = (px & 0x03e0) >> 5;
  70.             const sint32 b  = (px & 0x001f);
  71.             const sint32 yt = 8652*r + 16986*g + 3299*b;
  72.             const sint32 y  = (yt + 67584) >> 4;                            // <<8 alignment shift
  73.             const sint32 cr = (86436217*r - yt*2987 + 2155872256U) >> 8;    // <<16 alignment shift
  74.             const sint32 cb = (68373108*b - yt*2363 + 2155872256U) >> 24;
  75.  
  76.             *dst++ = (y&0xff00) + cb + (cr&0xff0000);        // VYU order
  77.         } while(--count);
  78.     }
  79.  
  80.     void ConvertRGB32ToY8(uint8 *dst, const uint8 *src, sint32 count) {
  81.         do {
  82.             const sint32 r  = src[2];
  83.             const sint32 g  = src[1];
  84.             const sint32 b  = src[0];
  85.             *dst++ = (uint8)((1052*r + 2065*g + 401*b + 67584) >> 12);
  86.             src += 4;
  87.         } while(--count);
  88.     }
  89.  
  90.     void ConvertRGB24ToY8(uint8 *dst, const uint8 *src, sint32 count) {
  91.         do {
  92.             const sint32 r  = src[2];
  93.             const sint32 g  = src[1];
  94.             const sint32 b  = src[0];
  95.             *dst++ = (uint8)((1052*r + 2065*g + 401*b + 67584) >> 12);
  96.             src += 3;
  97.         } while(--count);
  98.     }
  99.  
  100.     void ConvertRGB16ToY8(uint8 *dst, const uint16 *src, sint32 count) {
  101.         do {
  102.             const sint16 px = *src++;
  103.             const sint32 r  = (px & 0xf800) >> 11;
  104.             const sint32 g  = (px & 0x07e0) >> 5;
  105.             const sint32 b  = (px & 0x001f);
  106.             *dst++ = (uint8)((8652*r + 8358*g + 3299*b + 67584) >> 12);
  107.         } while(--count);
  108.     }
  109.  
  110.     void ConvertRGB15ToY8(uint8 *dst, const uint16 *src, sint32 count) {
  111.         do {
  112.             const sint16 px = *src++;
  113.             const sint32 r  = (px & 0x7c00) >> 10;
  114.             const sint32 g  = (px & 0x03e0) >> 5;
  115.             const sint32 b  = (px & 0x001f);
  116.             *dst++ = (uint8)((8652*r + 16986*g + 3299*b + 67584) >> 12);
  117.         } while(--count);
  118.     }
  119. }
  120.  
  121. #define DECLARE_YUV_REV(x, y) void VDPixmapBlt_##x##_to_##y##_reference(void *dst0, ptrdiff_t dstpitch, const void *src0, ptrdiff_t srcpitch, vdpixsize w, vdpixsize h)
  122.  
  123. DECLARE_YUV_REV(XRGB1555, XVYU) {
  124.     do {
  125.         ConvertRGB15ToXVYU32((uint32 *)dst0, (const uint16 *)src0, w);
  126.  
  127.         vdptrstep(dst0, dstpitch);
  128.         vdptrstep(src0, srcpitch);
  129.     } while(--h);
  130. }
  131.  
  132. DECLARE_YUV_REV(RGB565, XVYU) {
  133.     do {
  134.         ConvertRGB16ToXVYU32((uint32 *)dst0, (const uint16 *)src0, w);
  135.  
  136.         vdptrstep(dst0, dstpitch);
  137.         vdptrstep(src0, srcpitch);
  138.     } while(--h);
  139. }
  140.  
  141. DECLARE_YUV_REV(RGB888, XVYU) {
  142.     do {
  143.         ConvertRGB24ToXVYU32((uint32 *)dst0, (const uint8 *)src0, w);
  144.  
  145.         vdptrstep(dst0, dstpitch);
  146.         vdptrstep(src0, srcpitch);
  147.     } while(--h);
  148. }
  149.  
  150. DECLARE_YUV_REV(XRGB8888, XVYU) {
  151.     do {
  152.         ConvertRGB32ToXVYU32((uint32 *)dst0, (const uint8 *)src0, w);
  153.  
  154.         vdptrstep(dst0, dstpitch);
  155.         vdptrstep(src0, srcpitch);
  156.     } while(--h);
  157. }
  158.  
  159. DECLARE_YUV_REV(XRGB1555, Y8) {
  160.     do {
  161.         ConvertRGB15ToY8((uint8 *)dst0, (const uint16 *)src0, w);
  162.  
  163.         vdptrstep(dst0, dstpitch);
  164.         vdptrstep(src0, srcpitch);
  165.     } while(--h);
  166. }
  167.  
  168. DECLARE_YUV_REV(RGB565, Y8) {
  169.     do {
  170.         ConvertRGB16ToY8((uint8 *)dst0, (const uint16 *)src0, w);
  171.  
  172.         vdptrstep(dst0, dstpitch);
  173.         vdptrstep(src0, srcpitch);
  174.     } while(--h);
  175. }
  176.  
  177. DECLARE_YUV_REV(RGB888, Y8) {
  178.     do {
  179.         ConvertRGB24ToY8((uint8 *)dst0, (const uint8 *)src0, w);
  180.  
  181.         vdptrstep(dst0, dstpitch);
  182.         vdptrstep(src0, srcpitch);
  183.     } while(--h);
  184. }
  185.  
  186. DECLARE_YUV_REV(XRGB8888, Y8) {
  187.     do {
  188.         ConvertRGB32ToY8((uint8 *)dst0, (const uint8 *)src0, w);
  189.  
  190.         vdptrstep(dst0, dstpitch);
  191.         vdptrstep(src0, srcpitch);
  192.     } while(--h);
  193. }
  194.  
  195.  
  196.  
  197.  
  198.  
  199. namespace {
  200.     void ConvertRGB32ToYUVPlanar(uint8 *ydst, uint8 *cbdst, uint8 *crdst, const void *src0, sint32 count) {
  201.         const uint8 *src = (const uint8 *)src0;
  202.  
  203.         do {
  204.             const sint32 r  = src[2];
  205.             const sint32 g  = src[1];
  206.             const sint32 b  = src[0];
  207.             const sint32 yt = 1052*r + 2065*g + 401*b;
  208.             *ydst++  = (yt + 67584) >> 12;
  209.             *crdst++ = (10507932*r - yt*2987 + 2155872256U) >> 24;
  210.             *cbdst++ = ( 8312025*b - yt*2363 + 2155872256U) >> 24;
  211.             src += 4;
  212.         } while(--count);
  213.     }
  214.  
  215.     void ConvertRGB24ToYUVPlanar(uint8 *ydst, uint8 *cbdst, uint8 *crdst, const void *src0, sint32 count) {
  216.         const uint8 *src = (const uint8 *)src0;
  217.  
  218.         do {
  219.             const sint32 r  = src[2];
  220.             const sint32 g  = src[1];
  221.             const sint32 b  = src[0];
  222.             const sint32 yt = 1052*r + 2065*g + 401*b;
  223.             *ydst++  = (yt + 67584) >> 12;
  224.             *crdst++ = (10507932*r - yt*2987 + 2155872256U) >> 24;
  225.             *cbdst++ = ( 8312025*b - yt*2363 + 2155872256U) >> 24;
  226.             src += 3;
  227.         } while(--count);
  228.     }
  229.  
  230.     void ConvertRGB16ToYUVPlanar(uint8 *ydst, uint8 *cbdst, uint8 *crdst, const void *src0, sint32 count) {
  231.         const uint16 *src = (const uint16 *)src0;
  232.  
  233.         do {
  234.             const sint16 px = *src++;
  235.             const sint32 r  = (px & 0xf800) >> 11;
  236.             const sint32 g  = (px & 0x07e0) >> 5;
  237.             const sint32 b  = (px & 0x001f);
  238.             const sint32 yt = 8652*r + 8358*g + 3299*b;
  239.             *ydst++  = (yt + 67584) >> 12;
  240.             *crdst++ = (86436217*r - yt*2987 + 2155872256U) >> 24;
  241.             *cbdst++ = (68373108*b - yt*2363 + 2155872256U) >> 24;
  242.         } while(--count);
  243.     }
  244.  
  245.     void ConvertRGB15ToYUVPlanar(uint8 *ydst, uint8 *cbdst, uint8 *crdst, const void *src0, sint32 count) {
  246.         const uint16 *src = (const uint16 *)src0;
  247.  
  248.         do {
  249.             const sint16 px = *src++;
  250.             const sint32 r  = (px & 0x7c00) >> 10;
  251.             const sint32 g  = (px & 0x03e0) >> 5;
  252.             const sint32 b  = (px & 0x001f);
  253.             const sint32 yt = 8652*r + 16986*g + 3299*b;
  254.             *ydst++  = (yt + 67584) >> 12;
  255.             *crdst++ = (86436217*r - yt*2987 + 2155872256U) >> 24;
  256.             *cbdst++ = (68373108*b - yt*2363 + 2155872256U) >> 24;
  257.         } while(--count);
  258.     }
  259.  
  260.     void ConvertUYVYToYUVPlanar(uint8 *ydst, uint8 *cbdst, uint8 *crdst, const void *src0, sint32 count) {
  261.         const uint8 *src = (const uint8 *)src0;
  262.  
  263.         do {
  264.             *cbdst++ = src[0];
  265.             *ydst++ = src[1];
  266.             *crdst++ = src[2];
  267.             if (!--count)
  268.                 break;
  269.             *ydst++ = src[3];
  270.             src += 4;
  271.         } while(--count);
  272.     }
  273.  
  274.     void ConvertYUYVToYUVPlanar(uint8 *ydst, uint8 *cbdst, uint8 *crdst, const void *src0, sint32 count) {
  275.         const uint8 *src = (const uint8 *)src0;
  276.  
  277.         do {
  278.             *cbdst++ = src[1];
  279.             *ydst++ = src[0];
  280.             *crdst++ = src[3];
  281.             if (!--count)
  282.                 break;
  283.             *ydst++ = src[2];
  284.             src += 4;
  285.         } while(--count);
  286.     }
  287. }
  288.  
  289. void VDPixmapBlt_YUVPlanar_encode_reference(const VDPixmap& dstbm, const VDPixmap& srcbm, vdpixsize w, vdpixsize h) {
  290.     void (*cfunc)(uint8 *ydst, uint8 *cbdst, uint8 *crdst, const void *src, sint32 w) = NULL;
  291.     void (*hfunc)(uint8 *dst, const uint8 *src, sint32 w) = NULL;
  292.     void (*vfunc)(uint8 *dst, const uint8 *const *sources, sint32 w, uint8 phase) = NULL;
  293.  
  294.     bool halfchroma = false;
  295.  
  296.     switch(srcbm.format) {
  297.     case nsVDPixmap::kPixFormat_XRGB1555:
  298.         cfunc = ConvertRGB15ToYUVPlanar;
  299.         break;
  300.     case nsVDPixmap::kPixFormat_RGB565:
  301.         cfunc = ConvertRGB16ToYUVPlanar;
  302.         break;
  303.     case nsVDPixmap::kPixFormat_RGB888:
  304.         cfunc = ConvertRGB24ToYUVPlanar;
  305.         break;
  306.     case nsVDPixmap::kPixFormat_XRGB8888:
  307.         cfunc = ConvertRGB32ToYUVPlanar;
  308.         break;
  309.     case nsVDPixmap::kPixFormat_YUV422_UYVY:
  310.         cfunc = ConvertUYVYToYUVPlanar;
  311.         halfchroma = true;
  312.         break;
  313.     case nsVDPixmap::kPixFormat_YUV422_YUYV:
  314.         cfunc = ConvertYUYVToYUVPlanar;
  315.         halfchroma = true;
  316.         break;
  317.     default:
  318.         VDNEVERHERE;
  319.         return;
  320.     }
  321.  
  322.     vdpixsize w2 = w;
  323.     vdpixsize h2 = h;
  324.     int winstep = 1;
  325.     int winsize = 1;
  326.     int winposnext = 0;
  327.     vdpixsize chroma_srcw = w;
  328.  
  329.     switch(dstbm.format) {
  330.  
  331.     case nsVDPixmap::kPixFormat_YUV444_Planar:
  332.         if (halfchroma)
  333.             hfunc = horiz_expand2x_coaligned;
  334.         break;
  335.  
  336.     case nsVDPixmap::kPixFormat_YUV422_Planar:
  337.         if (halfchroma)
  338.             chroma_srcw = (chroma_srcw + 1) >> 1;
  339.         else
  340.             hfunc = horiz_compress2x_coaligned;
  341.  
  342.         w2 = (w2+1) >> 1;
  343.         break;
  344.  
  345.     case nsVDPixmap::kPixFormat_YUV420_Planar:
  346.         if (halfchroma)
  347.             chroma_srcw = (chroma_srcw + 1) >> 1;
  348.         else
  349.             hfunc = horiz_compress2x_coaligned;
  350.  
  351.         vfunc = vert_compress2x_centered;
  352.         winstep = 2;
  353.         winposnext = 2;
  354.         winsize = 4;
  355.         h2 = (h+1) >> 1;
  356.         w2 = (w2+1) >> 1;
  357.         break;
  358.  
  359.     case nsVDPixmap::kPixFormat_YUV411_Planar:
  360.         if (halfchroma) {
  361.             chroma_srcw = (chroma_srcw + 1) >> 1;
  362.             hfunc = horiz_compress2x_coaligned;
  363.         } else
  364.             hfunc = horiz_compress4x_coaligned;
  365.         w2 = (w2+1) >> 2;
  366.         break;
  367.  
  368.     case nsVDPixmap::kPixFormat_YUV410_Planar:
  369.         if (halfchroma) {
  370.             chroma_srcw = (chroma_srcw + 1) >> 1;
  371.             hfunc = horiz_compress2x_coaligned;
  372.         } else
  373.             hfunc = horiz_compress4x_coaligned;
  374.         vfunc = vert_compress4x_centered;
  375.         winsize = 8;
  376.         winposnext = 5;
  377.         winstep = 4;
  378.         h2 = (h+3) >> 2;
  379.         w2 = (w2+3) >> 2;
  380.         break;
  381.     }
  382.  
  383.     const uint8 *src = (const uint8 *)srcbm.data;
  384.     const ptrdiff_t srcpitch = srcbm.pitch;
  385.  
  386.     uint8 *ydst = (uint8 *)dstbm.data;
  387.     uint8 *cbdst = (uint8 *)dstbm.data2;
  388.     uint8 *crdst = (uint8 *)dstbm.data3;
  389.     const ptrdiff_t ydstpitch = dstbm.pitch;
  390.     const ptrdiff_t cbdstpitch = dstbm.pitch2;
  391.     const ptrdiff_t crdstpitch = dstbm.pitch3;
  392.  
  393.     if (!vfunc) {
  394.         if (hfunc) {
  395.             uint32 tmpsize = (w + 15) & ~15;
  396.  
  397.             vdblock<uint8> tmp(tmpsize * 2);
  398.             uint8 *const cbtmp = tmp.data();
  399.             uint8 *const crtmp = cbtmp + tmpsize;
  400.  
  401.             do {
  402.                 cfunc(ydst, cbtmp, crtmp, src, w);
  403.                 src += srcpitch;
  404.                 ydst += ydstpitch;
  405.                 hfunc(cbdst, cbtmp, chroma_srcw);
  406.                 hfunc(crdst, crtmp, chroma_srcw);
  407.                 cbdst += cbdstpitch;
  408.                 crdst += crdstpitch;
  409.             } while(--h);
  410.         } else if (dstbm.format == nsVDPixmap::kPixFormat_Y8) {
  411.             // wasteful, but oh well
  412.             uint32 tmpsize = (w2+15)&~15;
  413.             vdblock<uint8> tmp(tmpsize);
  414.  
  415.             cbdst = tmp.data();
  416.             crdst = cbdst + tmpsize;
  417.  
  418.             do {
  419.                 cfunc(ydst, cbdst, crdst, src, w);
  420.                 src += srcpitch;
  421.                 ydst += ydstpitch;
  422.             } while(--h2);
  423.         } else {
  424.             do {
  425.                 cfunc(ydst, cbdst, crdst, src, w);
  426.                 src += srcpitch;
  427.                 ydst += ydstpitch;
  428.                 cbdst += cbdstpitch;
  429.                 crdst += crdstpitch;
  430.             } while(--h2);
  431.         }
  432.     } else {
  433.         const uint32 tmpsize = w2;
  434.  
  435.         vdblock<uint8>        tmpbuf(tmpsize * (winsize + 1) * 2 + 2 * w);
  436.  
  437.         uint8 *cbwindow[16];
  438.         uint8 *crwindow[16];
  439.  
  440.         uint8 *p = tmpbuf.data();
  441.         for(int i=0; i<winsize; ++i) {
  442.             cbwindow[i] = cbwindow[winsize+i] = p;
  443.             p += tmpsize;
  444.             crwindow[i] = crwindow[winsize+i] = p;
  445.             p += tmpsize;
  446.         }
  447.  
  448.         uint8 *cbtmp = p;
  449.         uint8 *crtmp = p + w;
  450.  
  451.         int winoffset;
  452.         int winpos = winposnext - winsize;
  453.         bool firstline = true;
  454.  
  455.         do {
  456.             while(winpos < winposnext) {
  457.                 winoffset = ++winpos & (winsize - 1);
  458.  
  459.                 bool valid = (unsigned)(winpos-1) < (unsigned)(h-1);        // -1 because we generate line 0 as the first window line
  460.                 if (valid || firstline) {
  461.                     if (hfunc) {
  462.                         cfunc(ydst, cbtmp, crtmp, src, w);
  463.                         hfunc(cbwindow[winoffset + winsize - 1], cbtmp, chroma_srcw);
  464.                         hfunc(crwindow[winoffset + winsize - 1], crtmp, chroma_srcw);
  465.                     } else {
  466.                         cfunc(ydst, cbwindow[winoffset + winsize - 1], crwindow[winoffset + winsize - 1], src, w);
  467.                     }
  468.                     src += srcpitch;
  469.                     ydst += ydstpitch;
  470.                     firstline = false;
  471.                 } else {
  472.                     // dupe last generated line -- could be done by pointer swabbing, but I'm lazy
  473.                     memcpy(cbwindow[winoffset + winsize - 1], cbwindow[winoffset + winsize - 2], w2);
  474.                     memcpy(crwindow[winoffset + winsize - 1], crwindow[winoffset + winsize - 2], w2);
  475.                 }
  476.             }
  477.             winposnext += winstep;
  478.  
  479.             vfunc(cbdst, cbwindow + winoffset, w2, 0);
  480.             vfunc(crdst, crwindow + winoffset, w2, 0);
  481.             cbdst += cbdstpitch;
  482.             crdst += crdstpitch;
  483.         } while(--h2);
  484.     }
  485. }
  486.